package com.yex.service.modify.order;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.yex.common.exception.RRException;
import com.yex.dao.UserOrderDao;
import com.yex.entity.BankEntity;
import com.yex.entity.MerchantOrderEntity;
import com.yex.entity.UserEntity;
import com.yex.entity.UserOrderEntity;
import com.yex.entity.vo.UserOrderVo;
import com.yex.service.modify.BaseService;
import com.yex.service.modify.WalletService;
import com.yex.service.modify.bank.BankService;
import com.yex.util.CommonModifyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
@Transactional
public class UserOrderService extends BaseService<UserOrderDao, UserOrderEntity> {

    @Autowired
    private MerchantOrderService merchantOrderService;

    @Autowired
    private UserPriceService userPriceService;

    @Autowired
    private BankService bankService;


    private MerchantOrderEntity _validateMerchantOrder(UserOrderEntity userOrderEntity) {
        MerchantOrderEntity merchantOrderEntity = merchantOrderService.findById(userOrderEntity.getOrderId());
        if (merchantOrderEntity.getStatus() == 1) throw new RRException("该挂单已售罄");
        if (merchantOrderEntity.getIsCancel() == 1) throw new RRException("订单已关闭");
        return merchantOrderEntity;
    }

    private void _validateUserOrder(UserOrderEntity userOrderEntity, MerchantOrderEntity merchantOrderEntity) {
        if (userOrderEntity.getNumber().compareTo(merchantOrderEntity.getTotal()) > 0) {
            throw new RRException("购买数量必须小于: " + merchantOrderEntity.getTotal());
        }
        if (merchantOrderEntity.getMinSellerNumber().compareTo(userOrderEntity.getNumber()) > 0)
            throw new RRException("购买数量必须大于: " + merchantOrderEntity.getMinSellerNumber());
        if (merchantOrderEntity.getMaxSellerNumber().compareTo(userOrderEntity.getNumber()) < 0)
            throw new RRException("购买数量必须小于: " + merchantOrderEntity.getMaxSellerNumber());
        if (merchantOrderEntity.getTotal().compareTo(userOrderEntity.getNumber()) < 0) throw new RRException("输入数量有误");
    }

    private UserOrderEntity _createOrder(UserOrderEntity userOrderEntity) {
        userOrderEntity.setOrderNo(CommonModifyUtil.getOrderId());
        Integer count = baseMapper.insert(userOrderEntity);
        if (count > 1) throw new RRException("创建订单失败");
        return userOrderEntity;
    }

    private UserOrderEntity _findById(Integer userOrderId) {
        UserOrderEntity userOrderEntity = new UserOrderEntity();
        userOrderEntity.setId(userOrderId);
        userOrderEntity = baseMapper.selectOne(userOrderEntity);
        if (userOrderEntity == null) throw new RRException("无效的订单信息");
        if (userOrderEntity.getIsCancel() != 0) throw new RRException("订单已关闭");
        return userOrderEntity;
    }

    private List<UserOrderVo> _formatPrice(List<UserOrderVo> userOrderVos) {
        if (userOrderVos == null) return null;
//        userOrderVos.forEach(item -> {
//            BigDecimal totalPrice = item.getNumber().multiply(item.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
//            item.setTotalPrice(totalPrice);
//        });
        return userOrderVos;
    }

    /**
     * 用户订单已支付
     *
     * @param userOrderEntity
     */
    private void _payUserOrder(UserOrderEntity userOrderEntity) {
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("id", userOrderEntity.getId());
        userOrderEntity = new UserOrderEntity();
        userOrderEntity.setStatus(1);
        userOrderEntity.setPayTime(new Date());
        Integer count = baseMapper.update(userOrderEntity, wrapper);
        if (count > 1) throw new RRException("确认支付失败");
    }

    /**
     * 用户订单完成
     *
     * @param userOrderEntity
     */
    private void _completeUserOrder(UserOrderEntity userOrderEntity) {
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("id", userOrderEntity.getId());
        userOrderEntity = new UserOrderEntity();
        userOrderEntity.setCompleteTime(new Date());
        userOrderEntity.setStatus(2);
        Integer count = baseMapper.update(userOrderEntity, wrapper);
        if (count > 1) throw new RRException("确认支付失败");
    }

    /**
     * 完成订单之前,根据用户订单的id,得到相关的数据,并检测有效性
     *
     * @param userOrderId 用户订单id
     * @return
     */
    private Map<String, Object> _getCompleteOrderInfo(Integer userOrderId) {
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        UserOrderEntity userOrderEntity = _findById(userOrderId);
        MerchantOrderEntity merchantOrderEntity = merchantOrderService.findById(userOrderEntity.getOrderId());
        if (userOrderEntity.getStatus() != 1) {
            switch (userOrderEntity.getStatus()) {
                case 0:
                    throw new RRException("请先支付订单");
                case 2:
                    throw new RRException("订单已完成");
                default:
                    throw new RRException("无效的订单状态");
            }
        }
        Map<String, Object> returnData = new HashMap<>();
        returnData.put("user", userEntity);
        returnData.put("userOrder", userOrderEntity);
        returnData.put("merchantOrder", merchantOrderEntity);
        return returnData;
    }

    /**
     * 用户订单列表,根据买家用户id查询
     *
     * @param orderType 订单类型,非必填
     * @param status    订单状态,0,1,2
     * @param page      页码
     * @param rows      每页显示条数
     * @return
     */
    public Page<UserOrderVo> pageListByUser(Integer orderType, Integer status, Integer page, Integer rows) {
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        Page<UserOrderVo> pages = new Page<>(page, rows);
        return pages.setRecords(_formatPrice(baseMapper.selectOrderListByUser(pages, userEntity.getId(), orderType, status)));
    }

    /**
     * 用户订单列表,根据商户用户id查询
     *
     * @param orderType 订单类型,非必填
     * @param status    订单状态,0,1,2
     * @param page      页码
     * @param rows      每页显示条数
     * @return
     */
    public Page<UserOrderVo> pageListByMerchant(Integer orderType, Integer status, Integer page, Integer rows) {
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        Page<UserOrderVo> pages = new Page<>(page, rows);
        return pages.setRecords(_formatPrice(baseMapper.selectOrderListByMerchant(pages, userEntity.getId(), orderType, status)));
    }

    /**
     * 创建订单
     *
     * @param orderType       订单类型
     * @param userOrderEntity 创建订单相关参数
     * @return
     */
    public UserOrderEntity createOrder(Integer orderType, String moneyPassword, UserOrderEntity userOrderEntity) {
        //  验证当前登录用户
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        userOrderEntity.setUserId(userEntity.getId());
        CommonModifyUtil.checkPayPassword(moneyPassword, userEntity);
        //  验证当前用户银行卡信息
        if (userOrderEntity.getBankId() == null) {
            BankEntity bankEntity = bankService.getDefaultBank();
            userOrderEntity.setBankId(bankEntity.getId());
        }
        //  参数验证
        if (userOrderEntity.getNumber() == null) throw new RRException("请输入购买数量");

        //  得到挂单信息
        MerchantOrderEntity merchantOrderEntity = _validateMerchantOrder(userOrderEntity);

        //  计算总价
        BigDecimal totalPrice = userOrderEntity
                .getNumber().setScale(2, BigDecimal.ROUND_HALF_UP)
                .multiply(merchantOrderEntity.getPrice())
                .setScale(2, BigDecimal.ROUND_HALF_UP);

        //  订单参数配置
        userOrderEntity.setPrice(totalPrice);
        userOrderEntity.setCreateTime(new Date());
        userOrderEntity.setStatus(0);
        userOrderEntity.setIsCancel(0);

        //  验证订单有效性
        _validateUserOrder(userOrderEntity, merchantOrderEntity);
        //  冻结挂单余额
        merchantOrderService.frozen(userOrderEntity.getOrderId(), userOrderEntity.getNumber());

        //  根据订单类型,创建相应订单
        switch (orderType) {
            //  商家发布的买挂单
            case 1:
                //  判断挂单类型,冻结用户余额
                if (merchantOrderEntity.getOrderType() == 2) throw new RRException("无效的订单");
                userPriceService.frozen(userOrderEntity.getUserId(), userOrderEntity.getNumber());
                return _createOrder(userOrderEntity);
            case 2:
                if (merchantOrderEntity.getOrderType() == 1) throw new RRException("无效的订单");
                return _createOrder(userOrderEntity);
            default:
                throw new RRException("无效的订单类型");
        }
    }

    /**
     * 用户确定支付
     * 1    验证当前登录用户,并得到相关信息
     * 2    得到用户订单
     * 3    验证订单有效性
     * 4    验证挂单
     *
     * @param userOrderId 用户订单id
     */
    public void confirmPayByUser(Integer userOrderId, String moneyPassword) {
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        UserOrderEntity userOrderEntity = _findById(userOrderId);
        CommonModifyUtil.checkPayPassword(moneyPassword, userEntity);
        if (userOrderEntity.getStatus() != 0) throw new RRException("订单已支付");
        if (userOrderEntity.getUserId().compareTo(userEntity.getId()) != 0) throw new RRException("无效的订单信息");
        MerchantOrderEntity merchantOrderEntity = merchantOrderService.findById(userOrderEntity.getOrderId());
        if (merchantOrderEntity.getOrderType().compareTo(2) != 0) throw new RRException("无效的订单信息");
        _payUserOrder(userOrderEntity);
    }

    /**
     * 买单: 商家确认支付
     *
     * @param userOrderId
     */
    public void confirmPayByMerchant(Integer userOrderId, String moneyPassword) {
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        UserOrderEntity userOrderEntity = _findById(userOrderId);
        CommonModifyUtil.checkPayPassword(moneyPassword, userEntity);
        if (userOrderEntity.getStatus() != 0) throw new RRException("订单已支付");
        MerchantOrderEntity merchantOrderEntity = merchantOrderService.findById(userOrderEntity.getOrderId());
        if (merchantOrderEntity.getOrderType().compareTo(1) != 0) throw new RRException("无效的订单信息");
        if (merchantOrderEntity.getUserId().compareTo(userEntity.getId()) != 0) throw new RRException("无效的订单信息");
        _payUserOrder(userOrderEntity);
    }

    /**
     * 商户确认订单完成
     *
     * @param userOrderId 用户订单id
     */
    public void confirmOrderByMerchant(Integer userOrderId, String moneyPassword) {
        Map<String, Object> datas = _getCompleteOrderInfo(userOrderId);
        UserEntity userEntity = (UserEntity) datas.get("user");
        UserOrderEntity userOrderEntity = (UserOrderEntity) datas.get("userOrder");
        MerchantOrderEntity merchantOrderEntity = (MerchantOrderEntity) datas.get("merchantOrder");
        CommonModifyUtil.checkPayPassword(moneyPassword, userEntity);
        //  判断是否为自己可以操作的订单
        if (merchantOrderEntity.getUserId().compareTo(userEntity.getId()) != 0) throw new RRException("无效的订单信息");
        //  判断是否为以个卖单
        if (merchantOrderEntity.getOrderType().compareTo(2) != 0) throw new RRException("无效的订单信息");
        //  转账给买家
        userPriceService.transferUser(merchantOrderEntity.getUserId(), userOrderEntity.getUserId(), userOrderEntity.getNumber());
        //  判断商户挂单是否完成
        if (merchantOrderEntity.getTotal().subtract(userOrderEntity.getNumber()).compareTo(BigDecimal.ZERO) <= 0) {
            merchantOrderService.completeOrder(merchantOrderEntity.getId());
        }
        //  修改订单状态为完成
        _completeUserOrder(userOrderEntity);
    }

    /**
     * 用户确认订单完成
     *
     * @param userOrderId 用户订单id
     */
    public void confirmOrderByUser(Integer userOrderId, String moneyPassword) {
        Map<String, Object> datas = _getCompleteOrderInfo(userOrderId);
        UserEntity userEntity = (UserEntity) datas.get("user");
        UserOrderEntity userOrderEntity = (UserOrderEntity) datas.get("userOrder");
        MerchantOrderEntity merchantOrderEntity = (MerchantOrderEntity) datas.get("merchantOrder");
        CommonModifyUtil.checkPayPassword(moneyPassword, userEntity);
        //  判断是否为自己可以操作的订单
        if (userOrderEntity.getUserId().compareTo(userEntity.getId()) != 0) throw new RRException("无效的订单信息");
        //  判断是否为以个买单
        if (merchantOrderEntity.getOrderType().compareTo(1) != 0) throw new RRException("无效的订单信息");
        //  转账给商户
        userPriceService.transferUser(userOrderEntity.getUserId(), merchantOrderEntity.getUserId(), userOrderEntity.getNumber());
        //  判断商户挂单是否完成
        if (merchantOrderEntity.getTotal().subtract(userOrderEntity.getNumber()).compareTo(BigDecimal.ZERO) <= 0) {
            merchantOrderService.completeOrder(merchantOrderEntity.getId());
        }
        //  修改订单状态为完成
        _completeUserOrder(userOrderEntity);
    }

    /**
     * 取消订单
     *
     * @param id 用户订单id
     */
    public void cancelOrder(Integer id) {
        //  得到登录用户
        UserEntity userEntity = validateLoginUser(CommonModifyUtil.getRequest());
        //  得到关联的用户订单,验证是否属于登录用户
        UserOrderEntity userOrderEntity = _findById(id);
        if (userEntity.getId().compareTo(userOrderEntity.getUserId()) != 0) throw new RRException("无效的订单信息");
        //  得到关联的挂单信息
        MerchantOrderEntity merchantOrderEntity = merchantOrderService.findById(userOrderEntity.getOrderId());
        //  执行取消订单逻辑
        cancelOrderLogic(userOrderEntity, merchantOrderEntity);
    }

    /**
     * 取消订单逻辑
     *
     * @param userOrderEntity     用户订单
     * @param merchantOrderEntity 商户订单
     */
    public void cancelOrderLogic(UserOrderEntity userOrderEntity, MerchantOrderEntity merchantOrderEntity) {
        //  验证订单状态
        if (userOrderEntity.getStatus() == 2) throw new RRException("该订单已完成");
        if (userOrderEntity.getIsCancel() == 1) throw new RRException("该订单已撤销");
        if (userOrderEntity.getStatus().compareTo(0) != 0) throw new RRException("该订单已支付");
        //  解冻挂单数量
        merchantOrderService.unFrozen(merchantOrderEntity.getId(), userOrderEntity.getNumber());
        //  如果挂单是一个买单,那么解冻用户冻结数量
        if (merchantOrderEntity.getOrderType() == 1) {
            userPriceService.unfrozen(userOrderEntity.getUserId(), userOrderEntity.getNumber());
        }
        userOrderEntity.setIsCancel(1);
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("id", userOrderEntity.getId());
        Integer count = baseMapper.update(userOrderEntity, wrapper);
        if (count > 1) throw new RRException("撤销订单失败");
    }

    /**
     * 根据商户的挂单id,得到所有关联的用户订单
     *
     * @param orderId 商户挂单id
     * @return
     */
    public List<UserOrderEntity> getOrderByOrderId(Integer orderId) {
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("order_id", orderId).eq("is_cancel", "0");
        return baseMapper.selectList(wrapper);
    }

    /**
     * 得到过期的用户订单(2分钟超时)
     *
     * @return
     */
    public List<UserOrderEntity> getExpireOrders() {
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        Long currentTime = (System.currentTimeMillis() / 1000 - (60 * 2)) * 1000;
//        LocalTime.now().
        System.out.println(new Date(currentTime));
        wrapper.lt("create_time", new Date(currentTime)).eq("status", 0).eq("is_cancel", 0);
        return baseMapper.selectList(wrapper);
    }

    public UserOrderEntity findById(Integer userOrderId) {
        EntityWrapper<UserOrderEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("id", userOrderId);
        List<UserOrderEntity> findOrder = baseMapper.selectList(wrapper);
        if (findOrder == null || findOrder.size() == 0) throw new RRException("无效的订单信息");
        return findOrder.get(0);
    }

    public UserOrderEntity findRelationData(Integer userOrderId) {
        UserOrderEntity userOrderEntity = this.findById(userOrderId);
        userOrderEntity.setMerchantOrderEntity(merchantOrderService.findById(userOrderEntity.getOrderId()));
        userOrderEntity.setUserBank(bankService.findDataById(userOrderEntity.getBankId()));
        userOrderEntity.setMerchantBank(bankService.findDataById(userOrderEntity.getMerchantOrderEntity().getBankId()));
        return userOrderEntity;
    }

}
